package com.futvan.z.framework.util;

import com.futvan.z.framework.common.bean.Code;
import com.futvan.z.framework.common.bean.Result;
import com.futvan.z.framework.core.z;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import net.coobird.thumbnailator.Thumbnails;
import org.json.JSONArray;
import org.json.JSONObject;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Base64;
import java.util.Map;

/**
 * 图片工具类
 * @author 4223947@qq.com
 *
 */
public class ImgUtil {
	// 二维码尺寸
	private static final int QRCODE_SIZE = 300;
	// LOGO尺寸
	private static final int LOGO_SIZE = 50;


	public static void main(String[] args) throws Exception {
		String d = "";
		
		System.out.println(Base64ToImg("d:/bbb.png", d));
	}

	/**
	 * 通过阿里云解析发票服务，解析本地发票文件，获取内容  每次解析0.15元
	 * @param filepath 发票文件路径【绝对路径】
	 * @return
	 * @throws Exception 
	 */
	public static Result analysisInvoice(String filepath) throws Exception {
		Result result = new Result();
		File f = new File(filepath);
		if(z.isNotNull(f) && f.isFile()) {
			String host = "https://ocrapi-mixed-multi-invoice.taobao.com/ocrservice/mixedMultiInvoice";
			//设置头参数
			Map<String, String> headers = new HashMap<String, String>();
			//设置AppCode 中间用空格分隔
			headers.put("Authorization", "APPCODE 9aaeabd5d8e14ed19f3d4775dc882d20");
			headers.put("Content-Type", "application/json; charset=UTF-8");
			Map<String, String> querys = new HashMap<String, String>();
			String imginfo = ImageToBase64(filepath);
			querys.put("img", imginfo);
			String bodys = "{\"img\":\""+imginfo+"\"}";
			
			String response = HttpUtil.doPost2(host, headers, querys, bodys);
			try {
				
				JSONObject jsonObject = new JSONObject(response);
				if(!jsonObject.isNull("sid")) {
					JSONArray subMsgs = jsonObject.getJSONArray("subMsgs");
					JSONObject fpjson = subMsgs.getJSONObject(0).getJSONObject("result").getJSONObject("data");
					HashMap rmap = JsonUtil.getObject(fpjson.toString(), HashMap.class);
					result.setCode(Code.SUCCESS);
					result.setData(rmap);
				}else {
					result.setCode(Code.ERROR);
					result.setMsg("解析发票异常|"+response);
				}
			} catch (Exception e) {
				result.setCode(Code.ERROR);
				result.setMsg("解析发票异常|"+response);
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("发票文件未找到|"+filepath);
		}
		return result;
	}

	public static Result Base64ToImg(String path,String imgdate) {
		Result result = new Result();
		if(z.isNotNull(imgdate)) {
			Base64.Decoder decoder = Base64.getDecoder();
			//去掉base64,头描述信息
			if(imgdate.indexOf(";base64,")>=0) {
				imgdate = imgdate.substring(imgdate.indexOf(";base64,")+8);
			}
	        try {
	            // Base64解码
	            byte[] bytes = decoder.decode(imgdate);
	            for (int i = 0; i < bytes.length; ++i) {
	                if (bytes[i] < 0) {// 调整异常数据
	                    bytes[i] += 256;
	                }
	            }
	            // 生成jpeg图片
	            OutputStream out = new FileOutputStream(path);
	            out.write(bytes);
	            out.flush();
	            out.close();
	            result.setCode(Code.SUCCESS);
	            result.setMsg("转换成功");
	        } catch (Exception e) {
	        	result.setCode(Code.ERROR);
	        	result.setMsg(e.getMessage());
	        }
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("imgdate is null");
		}
		return result;
	}


	/**
	 * 本地图片转换Base64的方法
	 *
	 * @param imgPath     
	 */
	private static String ImageToBase64(String imgPath) {
		byte[] data = null;
		// 读取图片字节数组
		try {
			InputStream in = new FileInputStream(imgPath);
			data = new byte[in.available()];
			in.read(data);
			in.close();
		} catch (IOException e) {
			z.Error("ImageToBase64出错", e);
		}
		// 对字节数组Base64编码
		Base64.Encoder encoder = Base64.getEncoder();
		// 返回Base64编码过的字节数组字符串
		return encoder.encodeToString(data);
	}

	public static String getImgZ1Path(String img_url) {
		if(img_url.indexOf("_z5.")>=0){
			return img_url.replace("_z5.", "_z1.");
		}else if(img_url.indexOf("_z1.")>=0) {
			return img_url;
		}else {
			return img_url.replace(".", "_z1.");
		}
	}

	/**
	 * 	判读文件名称是否是图片类型
	 * @param filename
	 * @return
	 */
	public static boolean isImg(String filename) {
		boolean result = false;
		if(z.isNotNull(filename)) {
			if(filename.indexOf(".jpg")>=0){
				result = true;
			}else if(filename.indexOf(".png")>=0) {
				result = true;
			}else if(filename.indexOf(".jpeg")>=0) {
				result = true;
			}else if(filename.indexOf(".bmp")>=0) {
				result = true;
			}else if(filename.indexOf(".gif")>=0) {
				result = true;
			}else if(filename.indexOf(".tiff")>=0) {
				result = true;
			}else if(filename.indexOf(".raw")>=0) {
				result = true;
			}
		}
		return result;
	}

	public static String ImgZip(String img_path) {
		String new_img_path = "";
		if(isImg(img_path)) {
			try {
				//其中的scale是可以指定图片的大小，值在0到1之间，1f就是原图大小，0.5就是原图的一半大小，这里的大小是指图片的长宽。
				//而outputQuality是图片的质量，值也是在0到1，越接近于1质量越好，越接近于0质量越差。
				String temp_img_path_50 = img_path.substring(0, img_path.lastIndexOf(".")) +"_z5." + img_path.substring(img_path.lastIndexOf(".")+1);
				Thumbnails.of(img_path).scale(0.5f).outputQuality(0.5f).toFile(temp_img_path_50);

				String temp_img_path_20 = img_path.substring(0, img_path.lastIndexOf(".")) +"_z1." + img_path.substring(img_path.lastIndexOf(".")+1);
				Thumbnails.of(img_path).scale(0.1f).outputQuality(0.5f).toFile(temp_img_path_20);

				new_img_path = temp_img_path_50;
			} catch (IOException e) {
				z.Error("压缩图片出错|原图片地址："+img_path, e);
			}
		}
		return new_img_path;

	}

	/**
	 * 解析二维码
	 * @param img
	 * @return
	 */
	public static Result AnalysisQRCode(File img) {
		Result result = new Result();
		if(z.isNotNull(img) && img.isFile()) {
			try {
				BufferedImage bufferedImage = ImageIO.read(img);
				LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
				Binarizer binarizer = new HybridBinarizer(source);
				BinaryBitmap bitmap = new BinaryBitmap(binarizer);
				HashMap<DecodeHintType, Object> decodeHints = new HashMap<DecodeHintType, Object>();
				decodeHints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
				com.google.zxing.Result decode_result = new MultiFormatReader().decode(bitmap, decodeHints);
				String info = decode_result.getText();
				if(z.isNotNull(info)) {
					result.setCode(Code.SUCCESS);
					result.setData(info);
				}else {
					result.setCode(Code.ERROR);
					result.setMsg("解析二维码出错：二维码解析后，信息为空");
				}
			} catch (Exception e) {
				result.setCode(Code.ERROR);
				result.setMsg("解析二维码出错："+StringUtil.ExceptionToString(e));
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("解析二维码出错：未找到二维码图片文件");
		}
		return result;
	}

	/**
	 * 	生成二维码【无Logo】
	 * @param content
	 * @return
	 */
	public static BufferedImage CreateQRCode(String content) {
		return CreateQRCode(content,null,QRCODE_SIZE,LOGO_SIZE);
	}

	/**
	 * 	生成二维码【有Logo】
	 * @param content
	 * @param logoUrl
	 * @return
	 */
	public static BufferedImage CreateQRCode(String content,String logoUrl) {
		return CreateQRCode(content,logoUrl,QRCODE_SIZE,LOGO_SIZE);
	}

	/**
	 * 	生成二维码
	 * @param content 生成二维码内容信息
	 * @return BufferedImage
	 */
	public static BufferedImage CreateQRCode(String content,String logoFilePath,int QRCODE_SIZE,int LOGO_SIZE) {
		BufferedImage image = null;

		try {
			//设置二维码纠错级别ＭＡＰ
			Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
			hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
			//创建比特矩阵(位矩阵)的QR码编码的字符串  
			BitMatrix bitMatrix = new MultiFormatWriter().encode(content,BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);// 生成矩阵

			// 输出图像
			image = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE, BufferedImage.TYPE_INT_RGB);
			for (int x = 0; x < QRCODE_SIZE; x++) {
				for (int y = 0; y < QRCODE_SIZE; y++) {
					image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
				}
			}

			//判断是否插入logo
			if(z.isNotNull(logoFilePath)) {
				insertImage(image, logoFilePath,QRCODE_SIZE,LOGO_SIZE);
			}

		} catch (Exception e) {
			z.Error("生成二维码出错", e);
		}
		return image;
	}

	/**
	 * 	生成二维码插入Logo
	 * @param image 二维码
	 * @throws Exception
	 */
	private static void insertImage(BufferedImage image, String logoFilePath,int QRCODE_SIZE,int LOGO_SIZE) throws Exception {
		File file = new File(logoFilePath);
		if(z.isNotNull(logoFilePath) && file.exists()) {
			Image src = ImageIO.read(new File(logoFilePath));

			// 插入LOGO
			Graphics2D graph = image.createGraphics();
			int x = (QRCODE_SIZE - LOGO_SIZE) / 2;
			int y = (QRCODE_SIZE - LOGO_SIZE) / 2;
			graph.drawImage(src, x, y, LOGO_SIZE, LOGO_SIZE, null);
			Shape shape = new RoundRectangle2D.Float(x, y, LOGO_SIZE, LOGO_SIZE, 6, 6);
			graph.setStroke(new BasicStroke(3f));
			graph.draw(shape);
			graph.dispose();

		}else {
			z.Error("生成二维码未找到Logo文件，无法生成带Logo的二维码。当前生成为普通的二维码。");
		}
	}

}
